#!/usr/bin/env python3 
# -*- coding:utf-8 -*-

# Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。

import itertools

naturals = itertools.count(1)  # count(1)表示从1开始输出 count(2)则从2开始
for i in naturals:
    print(i)
    if i == 10:
        break

# count 会创建一个无限的迭代器, 不指定退出条件无法停止
"""
默认参数:start=0, step=1
表示从0开始,每次加1
count(1,2): 表示从1开始,每次步长为2
"""

# cycle
# cycle 会把传入的一个序列无限重复下去
"""
cs = itertools.cycle("ABCD")
for c in cs:
    print(c)
"""

# 同样cycle()也无法停下来

# repeat: 可以无限重复元素,通过指定重复次数来停止
ns = itertools.repeat("A", 3)
for n in ns:
    print(n)
# 会输出3遍 A

# 无限序列虽然可以无限迭代下去,但是我们通过 takewhile()等函数根据条件来截取出一个有用的无线序列

nls = itertools.count(1)
ns = itertools.takewhile(lambda x: x < 20, nls)
print(list(ns))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

# itertools 提供的几个迭代器操作函数更加有用
# chain: chain 可以把一组迭代对象串联起来,行程一个更大的迭代器
for c in itertools.chain('ABC', 'XYZ'):
    print(c)
# 迭代效果：'A' 'B' 'C' 'X' 'Y' 'Z'

# groupby()
# groupby 可以把迭代器中相邻的元素重复挑出来放一起

for key, group in itertools.groupby("ABCAAACBAASDF"):
    print(key, list(group))
"""
A ['A']
B ['B']
C ['C']
A ['A', 'A', 'A']
C ['C']
B ['B']
A ['A', 'A']
S ['S']
D ['D']
F ['F']
"""
"""
实际上挑选规则是通过函数完成的，只要作用于函数的两个元素返回的值相等，这两个元素就被认为是在一组的，而函数返回值作为组的key。
如果我们要忽略大小写分组，就可以让元素'A'和'a'都返回相同的key：

"""

for key, group in itertools.groupby('ABCaAAcBAASdDF', lambda c: c.upper()):
    print(key, list(group))


# 计算圆周率
def pi(n):
    # 1.创建一个基数序列
    na = itertools.count(start=1, step=2)
    # 2.获得序列的当前 n 项 1,3,5,7,9...2*n-1
    odd = itertools.takewhile(lambda x: x < 2 * n - 1, na)
    odd_list = list(odd)
    # 3. 添加正负符号并用4除
    first = [4 / i for i in odd_list[::2]]
    second = [-4 / i for i in odd_list[1::2]]
    return sum(first + second)


print(pi(10))

na = itertools.count(start=1, step=2)
odd = itertools.takewhile(lambda x: x < 2 * 10 - 1, na)
old_list = list(odd)

print(old_list)
first = [4 / i for i in old_list[::2]]
print(first)

"""
itertools模块提供的全部是处理迭代功能的函数，它们的返回值不是list，
而是Iterator，只有用for循环迭代的时候才真正计算。

"""
